﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

using MASAS.MSM.DomainLayer.Model;

namespace MASAS.MSM.DomainLayer.Filtering
{

    /// <summary>
    /// Filter Manager class.
    /// </summary>
    internal class FilterManager
    {

        /// <summary>
        /// Applies the filters to the given entries.
        /// </summary>
        /// <param name="filters">The filters.</param>
        /// <param name="entries">The entries.</param>
        internal void ApplyFilters( List<Filter> filters, List<HubEntry> entries )
        {
            List<Filter> sortedFilters = filters.OrderBy( x => x.Priority ).ToList();
            
            foreach( Filter filter in sortedFilters )
            {
                if( filter.Enabled )
                {
                    ApplyFilter( filter, entries );
                }
            }
        }

        /// <summary>
        /// Applies the filter to the given entries.
        /// </summary>
        /// <param name="filter">The filter.</param>
        /// <param name="entries">The entries.</param>
        private void ApplyFilter( Filter filter, List<HubEntry> entries )
        {
            // Apply the filter to each individual entry...
            foreach( HubEntry entry in entries )
            {
                string      expr    = string.Empty;
                string      xmlData = string.Empty;
                XmlDocument doc     = new XmlDocument();

                // Dependaing on what part was requested, use the appropriate xml...
                if( filter.Type == FilterItemType.Entry )
                {
                    expr = "/atom:entry[" + filter.Value + "]";
                    xmlData = entry.FeedEntryXML;
                }
                else if( filter.Type == FilterItemType.Alert )
                {
                    expr = "/cap:alert[" + filter.Value + "]";
                    xmlData = entry.AlertXML;
                }

                if( xmlData != null && xmlData != string.Empty )
                {
                    doc.LoadXml( xmlData );

                    // Make sure the namespaces are good...
                    XmlNamespaceManager mgr = new XmlNamespaceManager( doc.NameTable );
                    mgr.AddNamespace( "atom", "http://www.w3.org/2005/Atom" );
                    mgr.AddNamespace( "cap", "urn:oasis:names:tc:emergency:cap:1.1" );
                    mgr.AddNamespace( "cap", "urn:oasis:names:tc:emergency:cap:1.2" );

                    // Apply the XPath expression...
                    XmlNodeList nodeList = null;

                    try
                    {
                        nodeList = doc.DocumentElement.SelectNodes( expr, mgr );
                    }
                    catch( Exception e )
                    {
                        Logging.Logger.AddLogEntry( "An error occured with Filter " + filter.Name + " (Value=" + filter.Value + ").", e );
                    }

                    if( nodeList.Count != 0 )
                    {
                        // If we have a node, then we can associate the success value to the item...
                        ApplyState( entry, filter.SuccessValue );
                    }
                }
            }
        }

        /// <summary>
        /// Applies the new state, if needed.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="filterState">State of the filter.</param>
        private void ApplyState( HubEntry entry, FilterStateType filterState )
        {
            // We can upgrade the state, but we won't downgrade!
            if( filterState > entry.FilterState )
            {
                entry.FilterState = filterState;
            }
        }

    }

}
